package ftp

import (
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/fatih/color"
	"github.com/jlaffaye/ftp"
	"gs-demo-ftp-sync/internal/config"
)

// Client FTP客户端
type Client struct {
	config     *config.Config
	conn       *ftp.ServerConn
	isConnected bool
}

// NewClient 创建新的FTP客户端
func NewClient(cfg *config.Config) *Client {
	return &Client{
		config: cfg,
	}
}

// Connect 连接到FTP服务器
func (c *Client) Connect() error {
	if c.isConnected {
		return nil
	}

	// 如果有旧连接，先关闭
	if c.conn != nil {
		c.conn.Quit()
		c.conn = nil
	}

	modeText := "被动模式"
	if !c.config.FTPPassive {
		modeText = "主动模式"
	}

	color.Blue("尝试连接到 %s:%d... (%s)", c.config.FTPHost, c.config.FTPPort, modeText)

	// 创建连接
	conn, err := ftp.Dial(fmt.Sprintf("%s:%d", c.config.FTPHost, c.config.FTPPort), 
		ftp.DialWithTimeout(time.Duration(c.config.FTPTimeout)*time.Millisecond))
	if err != nil {
		return fmt.Errorf("连接失败: %v", err)
	}

	// 登录
	err = conn.Login(c.config.FTPUser, c.config.FTPPassword)
	if err != nil {
		conn.Quit()
		return fmt.Errorf("登录失败: %v", err)
	}

	c.conn = conn
	c.isConnected = true
	color.Green("✓ FTP连接成功")
	return nil
}

// Disconnect 断开FTP连接
func (c *Client) Disconnect() error {
	if c.conn != nil && c.isConnected {
		err := c.conn.Quit()
		c.conn = nil
		c.isConnected = false
		color.Yellow("FTP连接已断开")
		return err
	}
	return nil
}

// TestConnection 测试连接
func (c *Client) TestConnection() error {
	color.Blue("测试FTP连接...")
	
	if err := c.Connect(); err != nil {
		return err
	}

	// 获取当前目录
	pwd, err := c.conn.CurrentDir()
	if err != nil {
		return fmt.Errorf("获取当前目录失败: %v", err)
	}

	color.Green("✓ 当前目录: %s", pwd)
	return nil
}

// EnsureDir 确保远程目录存在
func (c *Client) EnsureDir(remotePath string) error {
	if !c.isConnected {
		return fmt.Errorf("FTP未连接")
	}

	// 分割路径
	dirs := strings.Split(strings.Trim(remotePath, "/"), "/")
	currentPath := ""

	for _, dir := range dirs {
		if dir == "" {
			continue
		}
		currentPath += "/" + dir

		// 尝试创建目录
		err := c.conn.MakeDir(currentPath)
		if err != nil {
			// 如果目录已存在，忽略错误
			if !strings.Contains(err.Error(), "exists") && !strings.Contains(err.Error(), "550") {
				return fmt.Errorf("创建目录失败 %s: %v", currentPath, err)
			}
		}
	}

	return nil
}

// UploadFile 上传文件
func (c *Client) UploadFile(localPath, remotePath string) error {
	if !c.isConnected {
		if err := c.Connect(); err != nil {
			return err
		}
	}

	// 确保远程目录存在
	remoteDir := filepath.Dir(remotePath)
	if err := c.EnsureDir(remoteDir); err != nil {
		return err
	}

	// 打开本地文件
	file, err := os.Open(localPath)
	if err != nil {
		return fmt.Errorf("打开本地文件失败: %v", err)
	}
	defer file.Close()

	// 上传文件
	err = c.conn.Stor(remotePath, file)
	if err != nil {
		return fmt.Errorf("上传文件失败: %v", err)
	}

	color.Green("✓ 上传成功: %s → %s", localPath, remotePath)
	return nil
}

// DeleteFile 删除远程文件
func (c *Client) DeleteFile(remotePath string) error {
	if !c.isConnected {
		if err := c.Connect(); err != nil {
			return err
		}
	}

	err := c.conn.Delete(remotePath)
	if err != nil {
		return fmt.Errorf("删除文件失败: %v", err)
	}

	color.Yellow("✓ 删除成功: %s", remotePath)
	return nil
}

// SyncDirectory 同步目录
func (c *Client) SyncDirectory(localDir, remoteDir string) error {
	if !c.isConnected {
		if err := c.Connect(); err != nil {
			return err
		}
	}

	// 检查本地目录是否存在
	if _, err := os.Stat(localDir); os.IsNotExist(err) {
		return fmt.Errorf("本地目录不存在: %s", localDir)
	}

	color.Blue("开始同步目录: %s → %s", localDir, remoteDir)
	
	if err := c.syncDirectoryRecursive(localDir, remoteDir); err != nil {
		return err
	}

	color.Green("✓ 目录同步完成: %s", remoteDir)
	return nil
}

// syncDirectoryRecursive 递归同步目录
func (c *Client) syncDirectoryRecursive(localDir, remoteDir string) error {
	// 确保远程目录存在
	if err := c.EnsureDir(remoteDir); err != nil {
		return err
	}

	// 读取本地目录
	entries, err := os.ReadDir(localDir)
	if err != nil {
		return err
	}

	for _, entry := range entries {
		// 检查是否应该排除
		if c.shouldExclude(entry.Name()) {
			continue
		}

		localPath := filepath.Join(localDir, entry.Name())
		remotePath := remoteDir + "/" + entry.Name()

		if entry.IsDir() {
			// 递归处理子目录
			if err := c.syncDirectoryRecursive(localPath, remotePath); err != nil {
				return err
			}
		} else {
			// 上传文件
			if err := c.UploadFile(localPath, remotePath); err != nil {
				return err
			}
		}
	}

	return nil
}

// shouldExclude 检查是否应该排除文件
func (c *Client) shouldExclude(filename string) bool {
	for _, pattern := range c.config.ExcludePatterns {
		if strings.Contains(pattern, "*") {
			// 简单的通配符匹配
			if matched, _ := filepath.Match(pattern, filename); matched {
				return true
			}
		} else if filename == pattern || strings.Contains(filename, pattern) {
			return true
		}
	}
	return false
}

// GetChangedFiles 获取变更的文件（基于git状态）
func (c *Client) GetChangedFiles() ([]string, error) {
	// 这里可以集成git命令来获取变更文件
	// 暂时返回空，让调用者决定如何处理
	return []string{}, nil
}
